refactor logging (#582)
authortsteven4 <13596209+tsteven4@users.noreply.github.com>
Fri, 5 Jun 2020 19:21:34 +0000 (13:21 -0600)
committerGitHub <noreply@github.com>
Fri, 5 Jun 2020 19:21:34 +0000 (13:21 -0600)
* refactor logging to

allow the noreturn attribute on fatal() to be used by analysis
tools while still generating messages with an output stream.

* Add our own message handler.

This allows us to use stderr on windows.  The default message handler
routes QDebug messages to the debugger on windows.

* flush stdout before message logger writes to stderr.

* flush stdout before writing to standard error for fatal().

or else messages can appear in the wrong order on Windows.

18 files changed:
arcdist.cc
cet_util.cc
defs.h
fatal.cc
garmin_fit.cc
garmin_tables.cc
gbfile.cc
geojson.cc
gpx.cc
interpolate.cc
main.cc
qstarz_bl_1000.cc
src/core/logging.h
stmsdf.cc
subrip.cc
unicsv.cc
waypt.cc
xcsv.cc

index e75654a17523e2bd8d2e27abcb5b0fc6062baaa1..06eea19285fb174f12bf671ab7a6bfa7ea5aabc4 100644 (file)
@@ -71,10 +71,10 @@ void ArcDistanceFilter::arcdist_arc_disp_wpt_cb(const Waypoint* arcpt2)
           frac = 1.0;
         } else {
           if (waypointp == nullptr) {
-            Fatal() << "Internal error. Attempt to project through a waypoint that doesn't exist";
+            fatal(FatalMsg() << "Internal error. Attempt to project through a waypoint that doesn't exist");
           }
           if (arcpt1 == nullptr) {
-            Fatal() << "Internal error: Attempt to project waypoint without predecessor";
+            fatal(FatalMsg() << "Internal error: Attempt to project waypoint without predecessor");
           }
 
           dist = linedistprj(arcpt1->latitude,
index 9aab538214549230f4a75d50174a0db3909fdb7f..62bb3d2691d3212c84acceff87a2aa79e1c1908e 100644 (file)
@@ -49,7 +49,7 @@ cet_convert_init(const QString& cs_name, const int force)
       global_opts.codec = QTextCodec::codecForName(CSTR(cs_name));
     }
     if (!global_opts.codec) {
-      Fatal() << "Unsupported character set \"" << cs_name << ".";
+      fatal(FatalMsg() << "Unsupported character set \"" << cs_name << ".");
     }
   }
 }
diff --git a/defs.h b/defs.h
index 1fcfb56cc34f2503e3825eae07ec4e93c7beaea6..604d0252843dd96b1f65a0adb0304164e4088185 100644 (file)
--- a/defs.h
+++ b/defs.h
@@ -37,6 +37,7 @@
 #include "zlib.h"                 // doesn't really belong here, but is missing elsewhere.
 #endif
 
+#include <QtCore/QDebug>          // for QDebug
 #include <QtCore/QList>           // for QList, QList<>::const_reverse_iterator, QList<>::reverse_iterator
 #include <QtCore/QScopedPointer>  // for QScopedPointer
 #include <QtCore/QString>         // for QString
@@ -1062,6 +1063,7 @@ struct style_vecs_t {
 };
 extern const QVector<style_vecs_t> style_list;
 
+[[noreturn]] void fatal(QDebug& msginstance);
 [[noreturn]] void fatal(const char*, ...) PRINTFLIKE(1, 2);
 void is_fatal(int condition, const char*, ...) PRINTFLIKE(2, 3);
 void warning(const char*, ...) PRINTFLIKE(1, 2);
index 00868e057f9a32cb19e0162dd1bc7d68b1fbcccf..a28667d368cbdc8da73a0b8fb872bdbe5117ff2c 100644 (file)
--- a/fatal.cc
+++ b/fatal.cc
 
  */
 
-#include "defs.h"
-#include <cstdio>
-#include <cstdlib>
+#include <cstdarg>             // for va_end, va_list, va_start
+#include <cstdio>              // for vfprintf, stderr, fflush, fprintf, stdout
+#include <cstdlib>             // for exit
+
+#include "defs.h"              // for Fatal, debug_print, fatal, warning
+#include "src/core/logging.h"  // for FatalMsg
+
+
+[[noreturn]] void fatal(QDebug& msginstance)
+{
+  auto* myinstance = new FatalMsg;
+  myinstance->swap(msginstance);
+  delete myinstance;
+  exit(1);
+}
+
 [[noreturn]] void
 fatal(const char* fmt, ...)
 {
+  /* flush any buffered standard output */
+  fflush(stdout);
+
   va_list ap;
   va_start(ap, fmt);
   vfprintf(stderr, fmt, ap);
index d880056dac7bcb4ba5636899fb17ab33571ee1ea..4208fbcb02c413fed7378aef797dbd90af66a2df 100644 (file)
@@ -147,7 +147,7 @@ GarminFitFormat::fit_parse_header()
       if (crc != 0) {
         Warning().nospace() << MYNAME ": Header CRC mismatch in file " <<  fin->name << ".";
         if (!opt_recoverymode) {
-          Fatal().nospace() << MYNAME ": File " << fin->name << " is corrupt.  Use recoverymode option at your risk.";
+          fatal(FatalMsg().nospace() << MYNAME ": File " << fin->name << " is corrupt.  Use recoverymode option at your risk.");
         }
       } else if (global_opts.debug_level >= 1) {
         debug_print(1, MYNAME ": Header CRC verified.\n");
@@ -752,7 +752,7 @@ GarminFitFormat::fit_check_file_crc() const
   if (crc != 0) {
     Warning().nospace() << MYNAME ": File CRC mismatch in file " <<  fin->name << ".";
     if (!opt_recoverymode) {
-      Fatal().nospace() << MYNAME ": File " << fin->name << " is corrupt.  Use recoverymode option at your risk.";
+      fatal(FatalMsg().nospace() << MYNAME ": File " << fin->name << " is corrupt.  Use recoverymode option at your risk.");
     }
   } else if (global_opts.debug_level >= 1) {
     debug_print(1, MYNAME ": File CRC verified.\n");
index 2c48771cd5b9cc3eae65afba1ab324d51f4e308d..9dc350b0292700900bc56071953d6147fb4c2815 100644 (file)
@@ -651,8 +651,8 @@ gt_lookup_grid_type(const char* grid_name, const QString& module)
     }
   }
 
-  Fatal() << module << ": Unsupported grid (" << grid_name <<
-                       ". See GPSBabel help for supported grids.\n";
+  fatal(FatalMsg() << module << ": Unsupported grid (" << grid_name <<
+                       ". See GPSBabel help for supported grids.\n");
 
   return grid_unknown; /* (warnings) */
 }
@@ -701,8 +701,8 @@ gt_lookup_datum_index(const char* datum_str, const QString& module)
   }
 
   if (result < 0) {
-    Fatal() << module << ": Unsupported datum (" << datum_str <<
-                         "). See GPSBabel help for supported datums.";
+    fatal(FatalMsg() << module << ": Unsupported datum (" << datum_str <<
+                         "). See GPSBabel help for supported datums.");
   }
   return result;
 }
index f149b5b08ba2173d485c055f5b575879ce63a4c9..0884798c4b6dd58328ad9ed61343bb1ea40aa1d1 100644 (file)
--- a/gbfile.cc
+++ b/gbfile.cc
@@ -712,8 +712,8 @@ QByteArray gbfreadbuf(gbsize_t size, gbfile* file) {
   gbsize_t nbytes = gbfread(tmp.data(), 1, size, file);
 
   if (nbytes != size) {
-    Fatal() << file->module << "Attempted to read " << size <<
-    "bytes, but only " << nbytes << "were available.";
+    fatal(FatalMsg() << file->module << "Attempted to read " << size <<
+    "bytes, but only " << nbytes << "were available.");
   }
   return tmp;
 }
index 8f31744f58df526cb317b0011d6d7c08485b3089..7f11d2193d1edeb387024e7511fa1adc37b893a9 100644 (file)
@@ -145,7 +145,7 @@ GeoJsonFormat::read() {
        QJsonParseError error{};
        QJsonDocument document = QJsonDocument::fromJson(file_content.toUtf8(), &error);
   if (error.error != QJsonParseError::NoError) {
-    Fatal().nospace() << MYNAME << ": GeoJSON parse error in " << ifd->fileName() << ": " << error.errorString();
+    fatal(FatalMsg().nospace() << MYNAME << ": GeoJSON parse error in " << ifd->fileName() << ": " << error.errorString());
   }
        QJsonObject rootObject = document.object();
 
diff --git a/gpx.cc b/gpx.cc
index bb10603aa4a7283ffe8644844438983366e960ff..2fc109fffacfbeafab3352d4c08baf615549d20a 100644 (file)
--- a/gpx.cc
+++ b/gpx.cc
@@ -972,8 +972,8 @@ GpxFormat::wr_init(const QString& fname)
   // It's a good thing 0, 0.0, 0.0.0 aren't valid gpx versions,
   // normalization makes them null.
   if (gpx_write_version.isNull() || (gpx_write_version < gpx_1_0)) {
-    Fatal() << MYNAME ": gpx version number"
-            << gpx_write_version << "not valid.";
+    fatal(FatalMsg() << MYNAME ": gpx version number"
+            << gpx_write_version << "not valid.");
   }
 
   writer->setAutoFormatting(true);
@@ -1122,10 +1122,10 @@ GpxFormat::read()
   }
 
   if (reader->hasError())  {
-    Fatal() << MYNAME << "Read error:" << reader->errorString()
+    fatal(FatalMsg() << MYNAME << "Read error:" << reader->errorString()
             << "File:" << iqfile->fileName()
             << "Line:" << reader->lineNumber()
-            << "Column:" << reader->columnNumber();
+            << "Column:" << reader->columnNumber());
   }
 }
 
index bd8e1a348f2ef5af0555b48fba506fe8d28650ab..ae1df8ed0a4fc0fe7ccf4556f3e3d53489238032 100644 (file)
@@ -47,7 +47,7 @@ void InterpolateFilter::process()
   }
 
   if (backuproute.empty()) {
-    Fatal() << MYNAME ": Found no routes or tracks to operate on.";
+    fatal(FatalMsg() << MYNAME ": Found no routes or tracks to operate on.");
   }
 
   for (const auto* rte_old : qAsConst(backuproute)) {
@@ -93,7 +93,7 @@ void InterpolateFilter::process()
         double npts = 0;
         if (opt_time != nullptr) {
           if (!timespan.has_value()) {
-            Fatal() << MYNAME ": points must have valid times to interpolate by time!";
+            fatal(FatalMsg() << MYNAME ": points must have valid times to interpolate by time!");
           }
           // interpolate even if time is running backwards.
           npts = std::abs(timespan.value()) / max_time_step;
@@ -105,7 +105,7 @@ void InterpolateFilter::process()
           npts = distspan / max_dist_step;
         }
         if (!std::isfinite(npts) || (npts >= INT_MAX)) {
-          Fatal() << MYNAME ": interpolation interval too small!";
+          fatal(FatalMsg() << MYNAME ": interpolation interval too small!");
         }
 
         // Insert the required points
@@ -162,13 +162,13 @@ void InterpolateFilter::init()
 {
   char* fm;
   if ((opt_time != nullptr) && (opt_dist != nullptr)) {
-    Fatal() << MYNAME ": Can't interpolate on both time and distance.";
+    fatal(FatalMsg() << MYNAME ": Can't interpolate on both time and distance.");
   } else if ((opt_time != nullptr) && (opt_route != nullptr)) {
-    Fatal() << MYNAME ": Can't interpolate routes on time.";
+    fatal(FatalMsg() << MYNAME ": Can't interpolate routes on time.");
   } else if (opt_time != nullptr) {
     max_time_step = 1000 * strtod(opt_time, nullptr); // milliseconds
     if (max_time_step <= 0) {
-      Fatal() << MYNAME ": interpolation time should be positve!";
+      fatal(FatalMsg() << MYNAME ": interpolation time should be positve!");
     }
   } else if (opt_dist != nullptr) {
     max_dist_step = strtod(opt_dist, &fm);
@@ -177,10 +177,10 @@ void InterpolateFilter::init()
       max_dist_step *= kMilesPerKilometer;
     }
     if (max_dist_step <= 0) {
-      Fatal() << MYNAME ": interpolation distance should be positve!";
+      fatal(FatalMsg() << MYNAME ": interpolation distance should be positve!");
     }
   } else {
-    Fatal() << MYNAME ": No interval specified.";
+    fatal(FatalMsg() << MYNAME ": No interval specified.");
   }
 }
 
diff --git a/main.cc b/main.cc
index 2e289390cd4c678567f99886fb14209cbbe8f18d..5dd24e5c71679ca60cd51d17194c3307ba91275e 100644 (file)
--- a/main.cc
+++ b/main.cc
 
  */
 
-#include <clocale>                  // for setlocale, LC_NUMERIC, LC_TIME
-#include <csignal>                  // for signal, SIGINT, SIG_ERR
-#include <cstdio>                   // for printf, fgetc, stdin
-#include <cstring>                  // for strcmp
-
-#include <QtCore/QByteArray>        // for QByteArray
-#include <QtCore/QChar>             // for QChar
-#include <QtCore/QCoreApplication>  // for QCoreApplication
-#include <QtCore/QFile>             // for QFile
-#include <QtCore/QIODevice>         // for QIODevice::ReadOnly
-#include <QtCore/QLocale>           // for QLocale
-#include <QtCore/QStack>            // for QStack
-#include <QtCore/QString>           // for QString
-#include <QtCore/QStringList>       // for QStringList
-#include <QtCore/QSysInfo>          // for QSysInfo
-#include <QtCore/QTextCodec>        // for QTextCodec
-#include <QtCore/QTextStream>       // for QTextStream
-#include <QtCore/QtConfig>          // for QT_VERSION_STR
-#include <QtCore/QtGlobal>          // for qPrintable, qVersion, QT_VERSION, QT_VERSION_CHECK
+#include <clocale>                    // for setlocale, LC_NUMERIC, LC_TIME
+#include <csignal>                    // for signal, SIGINT, SIG_ERR
+#include <cstdio>                     // for printf, fflush, fgetc, fprintf, stderr, stdin, stdout
+#include <cstring>                    // for strcmp
+
+#include <QtCore/QByteArray>          // for QByteArray
+#include <QtCore/QChar>               // for QChar
+#include <QtCore/QCoreApplication>    // for QCoreApplication
+#include <QtCore/QFile>               // for QFile
+#include <QtCore/QIODevice>           // for QIODevice::ReadOnly
+#include <QtCore/QLocale>             // for QLocale
+#include <QtCore/QMessageLogContext>  // for QMessageLogContext
+#include <QtCore/QStack>              // for QStack
+#include <QtCore/QString>             // for QString
+#include <QtCore/QStringList>         // for QStringList
+#include <QtCore/QSysInfo>            // for QSysInfo
+#include <QtCore/QTextCodec>          // for QTextCodec
+#include <QtCore/QTextStream>         // for QTextStream
+#include <QtCore/QtConfig>            // for QT_VERSION_STR
+#include <QtCore/QtGlobal>            // for qPrintable, qVersion, QT_VERSION, QT_VERSION_CHECK
 
 #ifdef AFL_INPUT_FUZZING
 #include "argv-fuzz-inl.h"
 #endif
 
 #include "defs.h"
-#include "cet_util.h"               // for cet_convert_init, cet_convert_deinit
-#include "csv_util.h"               // for csv_linesplit
-#include "filter.h"                 // for Filter
-#include "filter_vecs.h"            // for FilterVecs
-#include "format.h"                 // for Format
-#include "inifile.h"                // for inifile_done, inifile_init
-#include "session.h"                // for start_session, session_exit, session_init
-#include "src/core/datetime.h"      // for DateTime
-#include "src/core/file.h"          // for File
-#include "src/core/usasciicodec.h"  // for UsAsciiCodec
-#include "vecs.h"                   // for Vecs
+#include "cet_util.h"                 // for cet_convert_init, cet_convert_deinit
+#include "csv_util.h"                 // for csv_linesplit
+#include "filter.h"                   // for Filter
+#include "filter_vecs.h"              // for FilterVecs
+#include "format.h"                   // for Format
+#include "inifile.h"                  // for inifile_done, inifile_init
+#include "session.h"                  // for start_session, session_exit, session_init
+#include "src/core/datetime.h"        // for DateTime
+#include "src/core/file.h"            // for File
+#include "src/core/usasciicodec.h"    // for UsAsciiCodec
+#include "vecs.h"                     // for Vecs
 
 #define MYNAME "main"
 // be careful not to advance argn passed the end of the list, i.e. ensure argn < qargs.size()
@@ -190,6 +191,13 @@ print_extended_info()
     "\n");
 }
 
+static void MessageHandler(QtMsgType /* type */, const QMessageLogContext& /* context */, const QString& msg)
+{
+  /* flush any buffered standard output */
+  fflush(stdout);
+  fprintf(stderr, "%s\n", qPrintable(msg));
+}
+
 static void
 signal_handler(int sig)
 {
@@ -686,6 +694,8 @@ main(int argc, char* argv[])
 #endif
   }
 
+  qInstallMessageHandler(MessageHandler);
+
   (void) new gpsbabel::UsAsciiCodec(); /* make sure a US-ASCII codec is available */
 
   global_opts.objective = wptdata;
index b09ea1ae57acbc27e23f04de6faa7fd8b192b833..f9a40db714baf9bc66eaeebc26114987f5d0db5a 100644 (file)
@@ -135,7 +135,7 @@ QstarzBL1000Format::qstarz_bl_1000_read_record(QDataStream& stream, route_head*
   stream >> unused2;
 
   if (stream.status() != QDataStream::Ok) {
-    Fatal() << MYNAME << ": File format error on " << read_fname << ". Perhaps this isn't a Qstarz BL-1000 file";
+    fatal(FatalMsg() << MYNAME << ": File format error on " << read_fname << ". Perhaps this isn't a Qstarz BL-1000 file");
   }
 
   BL1000_POINT_TYPE type;
@@ -171,7 +171,7 @@ QstarzBL1000Format::qstarz_bl_1000_read_record(QDataStream& stream, route_head*
   default:
     type = BL1000_POINT_TYPE_UNKNOWN;
 
-    Fatal() << MYNAME << ": File format error on " << read_fname << ". Unexpected value for RCR (record reason): " << rcr;
+    fatal(FatalMsg() << MYNAME << ": File format error on " << read_fname << ". Unexpected value for RCR (record reason): " << rcr);
 
     break;
   }
@@ -205,7 +205,7 @@ QstarzBL1000Format::qstarz_bl_1000_read_record(QDataStream& stream, route_head*
     fix = fix_unknown;
 
     if (type != BL1000_POINT_TYPE_UNKNOWN) {
-      Fatal() << MYNAME << ": File format error on " << read_fname << ". Unexpected value for fix quality: " << fixQuality;
+      fatal(FatalMsg() << MYNAME << ": File format error on " << read_fname << ". Unexpected value for fix quality: " << fixQuality);
     }
 
     break;
@@ -219,11 +219,11 @@ QstarzBL1000Format::qstarz_bl_1000_read_record(QDataStream& stream, route_head*
   // qDebug(waypoint)
 
   if ((waypoint->latitude < -90) || (waypoint->latitude > 90)) {
-    Fatal() << MYNAME << ": File format error on " << read_fname << ". Unexpected value for latitude: " << waypoint->latitude;
+    fatal(FatalMsg() << MYNAME << ": File format error on " << read_fname << ". Unexpected value for latitude: " << waypoint->latitude);
   }
 
   if ((waypoint->longitude < -180) || (waypoint->longitude > 180)) {
-    Fatal() << MYNAME << ": File format error on " << read_fname << ". Unexpected value for longitude: " << waypoint->longitude;
+    fatal(FatalMsg() << MYNAME << ": File format error on " << read_fname << ". Unexpected value for longitude: " << waypoint->longitude);
   }
 
   waypoint->altitude = altitude;
@@ -287,7 +287,7 @@ QstarzBL1000Format::read()
 {
   QFile file(read_fname);
   if (!file.open(QIODevice::ReadOnly)) {
-    Fatal() << MYNAME << ": Error opening file " << read_fname;
+    fatal(FatalMsg() << MYNAME << ": Error opening file " << read_fname);
   }
 
   QDataStream stream(&file);
index 73a58ac332c63e2874b9db80c44ac92b1ef13419..08480b76201ad52e5bda48a4873c6aa38f9e662a 100644 (file)
 #ifndef gpsbabel_logging_h_included
 #define gpsbabel_logging_h_included
 
-// A wrapper for QDebug that provides a sensible Warning() and Fatal()
+// A wrapper for QDebug that provides a sensible Warning() and FatalMsg()
 // with convenient functions, stream operators and manipulators.
 
-#include <QtCore/QDebug>       // for QDebug
-#include <QtCore/QFile>        // for QFile
-#include <QtCore/QIODevice>    // for QIODevice, QIODevice::WriteOnly
-#include <QtCore/QString>      // for QString
-#include <QtCore/QTextStream>  // for QTextStream
-#include <cstdio>              // for stderr
-#include <cstdlib>             // for exit
+#include <QtCore/QDebug>     // for QDebug
+#include <QtCore/QtGlobal>   // for QtCriticalMsg, QtWarningMsg
 
 
-class Warning : public QDebug {
+class Warning : public QDebug
+{
 public:
-  explicit Warning(bool fatal = false) : QDebug(&msg_), fatal_(fatal) {
-  }
-  ~Warning() {
-    QFile file;
-    file.open(stderr, QIODevice::WriteOnly);
-    QTextStream fileStream(&file);
-    fileStream << msg_ << '\n';
-    file.close();
-    if (fatal_) {
-      exit(1);
-    }
-  }
-private:
-  QString msg_;
-  bool fatal_;
+  explicit Warning() : QDebug(QtWarningMsg) {}
 };
 
-class Fatal : public Warning {
- public:
-  Fatal() : Warning(true) {}
+/*
+ * To use a FatalMsg pass it to fatal(), e.g.
+ * fatal(FatalMsg() << "bye bye");
+ *
+ * This
+ * 1) allows the noreturn attribute on fatal to be use by analysis
+ *    tools such as cppcheck.
+ * 2) allows fatal to throw an exception instead of calling exit.
+ *    This could be caught by main for a cleaner exit from a fatal error.
+ */ 
+class FatalMsg : public QDebug
+{
+public:
+  // We don't use QtFatalMsg here because we don't want the destructor to call abort.
+  explicit FatalMsg() : QDebug(QtCriticalMsg) {}
 };
 
 #endif //  gpsbabel_logging_h_included
index 40847b9590d78d9af4da424e44c25bef02012db8..1c04b1dde27faab81a76275477b27372fb7705fc 100644 (file)
--- a/stmsdf.cc
+++ b/stmsdf.cc
@@ -149,7 +149,7 @@ parse_header(char* line)
       } else if (key == "TYPE") {
         filetype = qstr.toInt(&ok);
         if (!ok) {
-          Fatal() << MYNAME << "Unknown file type " << key;
+          fatal(FatalMsg() << MYNAME << "Unknown file type " << key);
         }
         switch (filetype) {
         case 4:        /* M9 TrackLog (Suunto Sail Manager) */
@@ -278,7 +278,7 @@ parse_point(char *line) {
           auto year = v[2].toInt();
           dt = QDate(year, month, day);
         } else {
-          Fatal() << MYNAME << "Invalid date" << qstr;
+          fatal(FatalMsg() << MYNAME << "Invalid date" << qstr);
         }
         break;
       }
@@ -291,20 +291,20 @@ parse_point(char *line) {
           auto sec = v[2].toInt();
           tm = QTime(hour, min, sec);
         } else {
-          Fatal() << MYNAME << "Invalid Time" << qstr;
+          fatal(FatalMsg() << MYNAME << "Invalid Time" << qstr);
         }
         break;
       }
       case 4:
         wpt->latitude = qstr.toDouble(&ok);
         if (!ok) {
-          Fatal() << MYNAME << "Invalid latitude" << qstr;
+          fatal(FatalMsg() << MYNAME << "Invalid latitude" << qstr);
         }
         break;
       case 5:
         wpt->longitude = qstr.toDouble(&ok);
         if (!ok) {
-          Fatal() << MYNAME << "Invalid longitude" << qstr;
+          fatal(FatalMsg() << MYNAME << "Invalid longitude" << qstr);
         }
         break;
       case 6: {
index 7e32265aa40941868a0991b968a5206bfe7aa49f..707f7c1bc9ab5761a01a7a387736a09081a3b43d 100644 (file)
--- a/subrip.cc
+++ b/subrip.cc
@@ -202,19 +202,19 @@ SubripFormat::wr_init(const QString& fname)
   gradient = 0;
 
   if ((opt_gpstime == nullptr) != (opt_gpsdate == nullptr)) {
-    Fatal() << MYNAME ": Either both or neither of the gps_date and gps_time options must be supplied!";
+    fatal(FatalMsg() << MYNAME ": Either both or neither of the gps_date and gps_time options must be supplied!");
   }
   gps_datetime = QDateTime();
   if ((opt_gpstime != nullptr) && (opt_gpsdate != nullptr)) {
     QDate gps_date = QDate::fromString(opt_gpsdate, "yyyyMMdd");
     if (!gps_date.isValid()) {
-      Fatal().nospace() << MYNAME ": option gps_date value (" << opt_gpsdate << ") is invalid.  Expected yyyymmdd.";
+      fatal(FatalMsg().nospace() << MYNAME ": option gps_date value (" << opt_gpsdate << ") is invalid.  Expected yyyymmdd.");
     }
     QTime gps_time = QTime::fromString(opt_gpstime, "HHmmss");
     if (!gps_time.isValid()) {
       gps_time = QTime::fromString(opt_gpstime, "HHmmss.z");
       if (!gps_time.isValid()) {
-        Fatal().nospace() << MYNAME ": option gps_time value (" << opt_gpstime << ") is invalid.  Expected hhmmss[.sss]";
+        fatal(FatalMsg().nospace() << MYNAME ": option gps_time value (" << opt_gpstime << ") is invalid.  Expected hhmmss[.sss]");
       }
     }
     gps_datetime = QDateTime(gps_date, gps_time, Qt::UTC);
@@ -226,7 +226,7 @@ SubripFormat::wr_init(const QString& fname)
     if (!video_time.isValid()) {
       video_time = QTime::fromString(opt_videotime, "HHmmss.z");
       if (!video_time.isValid()) {
-        Fatal().nospace() << MYNAME ": option video_time value (" << opt_videotime << ") is invalid.  Expected hhmmss[.sss].";
+        fatal(FatalMsg().nospace() << MYNAME ": option video_time value (" << opt_videotime << ") is invalid.  Expected hhmmss[.sss].");
       }
     }
     video_offset_ms = video_time.msecsSinceStartOfDay();
index ab41748e9bec33f26b0e86c274a6dfa6c31cef75..1dc2d1e6fccdd6c4f20b20f72eae6034b127f727 100644 (file)
--- a/unicsv.cc
+++ b/unicsv.cc
@@ -244,7 +244,7 @@ UnicsvFormat::unicsv_parse_date(const char* str, int* consumed)
       *consumed = 0;   /* for a possible date */
       return 0;
     }
-    Fatal() << MYNAME << ": Could not parse date string (" << str << ").\n";
+    fatal(FatalMsg() << MYNAME << ": Could not parse date string (" << str << ").\n");
   }
 
   if ((p1 > 99) || (sep[0] == '-')) { /* Y-M-D (iso like) */
@@ -273,7 +273,7 @@ UnicsvFormat::unicsv_parse_date(const char* str, int* consumed)
       *consumed = 0;
       return 0;        /* don't stop here */
     }
-    Fatal() << MYNAME << ": Could not parse date string (" << str << ").\n";
+    fatal(FatalMsg() << MYNAME << ": Could not parse date string (" << str << ").\n");
   }
 
   tm.tm_year -= 1900;
@@ -1770,8 +1770,8 @@ void
 UnicsvFormat::unicsv_check_modes(bool test)
 {
   if (test) {
-    Fatal() << MYNAME <<
-            " : Invalid combination of -w, -t, -r selected. Use only one.";
+    fatal(FatalMsg() << MYNAME <<
+            " : Invalid combination of -w, -t, -r selected. Use only one.");
   }
 }
 
@@ -1796,7 +1796,7 @@ UnicsvFormat::write()
     route_disp_all(nullptr, nullptr, unicsv_waypt_enum_cb_lambda);
     break;
   case posndata:
-    Fatal() << MYNAME << ": Realtime positioning not supported.";
+    fatal(FatalMsg() << MYNAME << ": Realtime positioning not supported.");
   }
 
   *fout << "No" << unicsv_fieldsep;
index 15cfe3493c19cb5cdfbfb9db9a747f5466e88f1f..ac38d57c8da6a09bdbfef73b14f10832ab73984a 100644 (file)
--- a/waypt.cc
+++ b/waypt.cc
@@ -602,12 +602,12 @@ WaypointList::waypt_add(Waypoint* wpt)
   }
 
   if ((wpt->latitude < -90) || (wpt->latitude > 90.0))
-    Fatal() << wpt->session->name
+    fatal(FatalMsg() << wpt->session->name
             << "Invalid latitude" << lat_orig << "in waypoint"
-            << wpt->shortname;
+            << wpt->shortname);
   if ((wpt->longitude < -180) || (wpt->longitude > 180.0))
-    Fatal() << "Invalid longitude" << lon_orig << "in waypoint"
-            << wpt->shortname;
+    fatal(FatalMsg() << "Invalid longitude" << lon_orig << "in waypoint"
+            << wpt->shortname);
 
   /*
    * Some input may not have one or more of these types so we
diff --git a/xcsv.cc b/xcsv.cc
index c404fee78ecce3a513e1e4d786152d51d0912007..babc01d31a6210264b09e67d2ff26c79dcce8500 100644 (file)
--- a/xcsv.cc
+++ b/xcsv.cc
@@ -212,14 +212,14 @@ QString XcsvStyle::dequote(const QString& in) {
 
 void XcsvStyle::validate_fieldmap(const field_map& fmp, bool is_output) {
   if (fmp.key.isEmpty()) {
-    Fatal() << MYNAME << ": xcsv style is missing" <<
-            (is_output ? "output" : "input") << "field type.";
+    fatal(FatalMsg() << MYNAME << ": xcsv style is missing" <<
+            (is_output ? "output" : "input") << "field type.");
   }
   if (fmp.val.isNull()) {
-    Fatal() << MYNAME << ": xcsv style" << fmp.key.constData() << "is missing default.";
+    fatal(FatalMsg() << MYNAME << ": xcsv style" << fmp.key.constData() << "is missing default.");
   }
   if (is_output && fmp.printfc.isNull()) {
-    Fatal() << MYNAME << ": xcsv style" << fmp.key.constData() << "output is missing format specifier.";
+    fatal(FatalMsg() << MYNAME << ": xcsv style" << fmp.key.constData() << "output is missing format specifier.");
   }
 }
 
@@ -1759,13 +1759,13 @@ XcsvStyle::xcsv_parse_style_line(XcsvStyle* style, QString line)
     } else if (p == "WAYPOINT") {
       style->datatype = wptdata;
     } else {
-      Fatal() << MYNAME << ": Unknown data type" << p;
+      fatal(FatalMsg() << MYNAME << ": Unknown data type" << p);
     }
   } else
 
   if (op == "IFIELD") {
     if (tokens.size() < 3) {
-      Fatal() << "Invalid IFIELD line: " << tokenstr;
+      fatal(FatalMsg() << "Invalid IFIELD line: " << tokenstr);
     }
 
     // The key ("LAT_DIR") should never contain quotes.
@@ -1785,7 +1785,7 @@ XcsvStyle::xcsv_parse_style_line(XcsvStyle* style, QString line)
     unsigned options = 0;
       // Note: simplified() has to run after split().
     if (tokens.size() < 3) {
-      Fatal() << "Invalid OFIELD line: " << tokenstr;
+      fatal(FatalMsg() << "Invalid OFIELD line: " << tokenstr);
     }
 
     // The key ("LAT_DIR") should never contain quotes.